package com.shanxia.codec.cmd;

import com.shanxia.codec.Decoder;
import com.shanxia.codec.ProtocolDataBase;
import com.shanxia.codec.enums.DecodeEnum;
import lombok.Data;

import java.math.BigDecimal;
import java.util.Arrays;

import static com.shanxia.codec.CodeConstant.PERCENT;
import static com.shanxia.codec.Decoder.*;

/**
 * C -> S
 * 充电桩上报充电记录信息
 * 充电桩上报充电信息
 * TODO demo字节数不够，未通过测试
 */
@Data
public class Cmd202 extends ProtocolDataBase {

    public static final int MIN_SIZE = 293;

    private int v1;
    private int v2;
    private String sn;                              // 充电桩编码
    private int pilePosType;                        // 充电枪位置类型
    private int pilePort;                           // 充电枪口
    private String chargingCardNum;                 // 充电卡号
    private String chargingStartTime;               // 充电开始时间
    private String chargingEndTime;                 // 充电结束时间
    private int duration;                           // 充电时间长度
    private int startSoc;                           // 开始 SOC
    private int endSoc;                             // 结束 SOC
    private int endReason;                          // 充电结束原因
    private double chargingQuantity;                // 本次充电电量
    private double beforeChargingValue;             // 充电前电表读数
    private double afterChargingValue;              // 充电后电表读数
    private double chargingAmount;                  // 本次充电金额
    private int indexNum;                           // 内部索引号
    private double beforeChargingBalance;           // 充电前卡余额
    private int curIndex;                           // 当前充电记录索引
    private int totalRecordCount;                   // 总充电记录条目
    private int v3;                                 // 预留
    private int chargingStrategy;                   // 充电策略
    private String chargingStrategyParam;           // 充电策略参数
    private String vin;                             // 车辆 VIN
    private String carNum;                          // 车牌号
    private double t1ChargingQuantity;              // 时段1充电电量
    private double t2ChargingQuantity;              // 时段2充电电量
    private double t3ChargingQuantity;
    private double t4ChargingQuantity;
    private double t5ChargingQuantity;
    private double t6ChargingQuantity;
    private double t7ChargingQuantity;
    private double t8ChargingQuantity;
    private double t9ChargingQuantity;
    private double t10ChargingQuantity;
    private double t11ChargingQuantity;
    private double t12ChargingQuantity;
    private double t13ChargingQuantity;
    private double t14ChargingQuantity;
    private double t15ChargingQuantity;
    private double t16ChargingQuantity;
    private double t17ChargingQuantity;
    private double t18ChargingQuantity;
    private double t19ChargingQuantity;
    private double t20ChargingQuantity;
    private double t21ChargingQuantity;
    private double t22ChargingQuantity;
    private double t23ChargingQuantity;
    private double t24ChargingQuantity;
    private double t25ChargingQuantity;
    private double t26ChargingQuantity;
    private double t27ChargingQuantity;
    private double t28ChargingQuantity;
    private double t29ChargingQuantity;
    private double t30ChargingQuantity;
    private double t31ChargingQuantity;
    private double t32ChargingQuantity;
    private double t33ChargingQuantity;
    private double t34ChargingQuantity;
    private double t35ChargingQuantity;
    private double t36ChargingQuantity;
    private double t37ChargingQuantity;
    private double t38ChargingQuantity;
    private double t39ChargingQuantity;
    private double t40ChargingQuantity;
    private double t41ChargingQuantity;
    private double t42ChargingQuantity;
    private double t43ChargingQuantity;
    private double t44ChargingQuantity;
    private double t45ChargingQuantity;
    private double t46ChargingQuantity;
    private double t47ChargingQuantity;
    private double t48ChargingQuantity;
    private int startWay;                           // 启动方式
    private String serialNum;                       // 充电流水号
    private double serviceCost;                     // 充电服务费
    private double thousandthEnergy;                // 千分位电量

    public Cmd202(){
        super.setCmd(202);
    }

    public static Cmd202 decodeFromBase(ProtocolDataBase protocolDataBase) {
        Cmd202 cmd = new Cmd202();
        cmd.copyDataFrom(protocolDataBase);
        byte[] dataField = protocolDataBase.getDataField();
        //数据域长度
        if (dataField.length < MIN_SIZE) {
            cmd.setResult(DecodeEnum.InvalidData);
            return cmd;
        }
        int offset = 0;
        cmd.v1 = getUint16(dataField, offset);
        offset += 2;
        cmd.v2 = getUint16(dataField, offset);
        offset += 2;
        // 32字节充电桩编码
        cmd.sn = Decoder.byteToAscii(Arrays.copyOfRange(dataField, offset, offset + 32), true);
        offset += 32;
        // 1字节充电枪位置类型
        cmd.pilePosType = getUint8(dataField[offset++]);
        // 1字节充电枪口
        cmd.pilePort = getUint8(dataField[offset++]);
        // 32字节充电卡号
        cmd.chargingCardNum = byteToAscii(Arrays.copyOfRange(dataField, offset, offset + 32), true);
        offset += 32;
        // 8字节充电开始时间
        cmd.chargingStartTime = getStandardTime(dataField, offset);
        offset += 8;
        // 8字节充电结束时间
        cmd.chargingEndTime = getStandardTime(dataField, offset);
        offset += 8;
        // 4字节充电时间长度
        cmd.duration = getInt32(dataField, offset);
        offset += 4;
        // 1字节开始SOC
        cmd.startSoc = getUint8(dataField[offset++]);
        // 1字节结束SOC
        cmd.endSoc = getUint8(dataField[offset++]);
        // 4字节充电结束原因
        cmd.endReason = getInt32(dataField, offset);
        offset += 4;
        // 4字节本次充电量
        cmd.chargingQuantity = new BigDecimal(getInt32(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 4;
        // 4字节充电前电表读数
        cmd.beforeChargingValue = new BigDecimal(getInt32(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 4;
        // 4字节充电后电表读数
        cmd.afterChargingValue = new BigDecimal(getInt32(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 4;
        // 4字节本次充电金额
        cmd.chargingAmount = new BigDecimal(getInt32(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 4;
        // 4字节内部索引号
        cmd.indexNum = getInt32(dataField, offset);
        offset += 4;
        // 4字节充电前卡余额
        cmd.beforeChargingBalance = new BigDecimal(getInt32(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 4;
        // 4字节当前充电记录索引
        cmd.curIndex = getInt32(dataField, offset);
        offset += 4;
        // 4字节总充电记录条目
        cmd.totalRecordCount = getInt32(dataField, offset);
        offset += 4;
        // 1字节预留
        cmd.v3 = getUint8(dataField[offset++]);
        // 1字节充电策略
        cmd.chargingStrategy = getUint8(dataField[offset++]);
        // 4字节充电策略参数
        int param = getInt32(dataField, offset);
        if (cmd.chargingStrategy == 1 || cmd.chargingStrategy == 2) {
            cmd.chargingStrategyParam = String.valueOf(new BigDecimal(param).multiply(PERCENT));
        } else {
            cmd.chargingStrategyParam = String.valueOf(param);
        }
        offset += 4;
        // 17字节车辆 VIN
        cmd.vin = Decoder.byteToAscii(Arrays.copyOfRange(dataField, offset, offset + 17), true);
        offset += 17;
        // 8字节车牌号
        cmd.carNum = Decoder.byteToAscii(Arrays.copyOfRange(dataField, offset, offset + 8), true);
        offset += 8;
        // 2字节时段1充电电量
        cmd.t1ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段2充电电量
        cmd.t2ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段3充电电量
        cmd.t3ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段4充电电量
        cmd.t4ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段5充电电量
        cmd.t5ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段6充电电量
        cmd.t6ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段7充电电量
        cmd.t7ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段8充电电量
        cmd.t8ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段9充电电量
        cmd.t9ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段10充电电量
        cmd.t10ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段11充电电量
        cmd.t11ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段12充电电量
        cmd.t12ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段13充电电量
        cmd.t13ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段14充电电量
        cmd.t14ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段15充电电量
        cmd.t15ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段16充电电量
        cmd.t16ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段17充电电量
        cmd.t17ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段18充电电量
        cmd.t18ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段19充电电量
        cmd.t19ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段20充电电量
        cmd.t20ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段21充电电量
        cmd.t21ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段22充电电量
        cmd.t22ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段23充电电量
        cmd.t23ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段24充电电量
        cmd.t24ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段25充电电量
        cmd.t25ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段26充电电量
        cmd.t26ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段27充电电量
        cmd.t27ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段28充电电量
        cmd.t28ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段29充电电量
        cmd.t29ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段30充电电量
        cmd.t30ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段31充电电量
        cmd.t31ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段32充电电量
        cmd.t32ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段33充电电量
        cmd.t33ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段34充电电量
        cmd.t34ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段35充电电量
        cmd.t35ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段36充电电量
        cmd.t36ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段37充电电量
        cmd.t37ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段38充电电量
        cmd.t38ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段39充电电量
        cmd.t39ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段40充电电量
        cmd.t40ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段41充电电量
        cmd.t41ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段42充电电量
        cmd.t42ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段43充电电量
        cmd.t43ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段44充电电量
        cmd.t44ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段45充电电量
        cmd.t45ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段46充电电量
        cmd.t46ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段47充电电量
        cmd.t47ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 2字节时段48充电电量
        cmd.t48ChargingQuantity = new BigDecimal(getUint16(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 2;
        // 1字节启动方式
        cmd.startWay = getUint8(dataField[offset++]);
        // 32字节充电流水号
        cmd.serialNum = byteToAscii(Arrays.copyOfRange(dataField, offset, offset + 32), false);
        offset += 32;
        // 4字节充电服务费
        cmd.serviceCost = new BigDecimal(getInt32(dataField, offset)).multiply(PERCENT).doubleValue();
        offset += 4;
        // 1字节千分位电量
        cmd.thousandthEnergy = new BigDecimal(getUint8(dataField[offset++])).multiply(PERCENT).doubleValue();
        return cmd;
    }

    @Override
    public String toString() {

        StringBuffer buffer = new StringBuffer();
        buffer.append("#cmd202#").append("\n");
        buffer.append("v1:").append(v1).append("\n");
        buffer.append("v2:").append(v2).append("\n");
        buffer.append("充电桩编码:").append(sn).append("\n");
        buffer.append("充电枪位置类型:").append(pilePosType).append("\n");                        //
        buffer.append("充电枪口:").append(pilePort).append("\n");                           //
        buffer.append("充电卡号:").append(chargingCardNum).append("\n");                 //
        buffer.append("充电开始时间:").append(chargingStartTime).append("\n");               //
        buffer.append("充电结束时间:").append(chargingEndTime).append("\n");                 //
        buffer.append("充电时间长度:").append(duration).append("\n");                           //
        buffer.append("开始 SOC:").append(startSoc).append("\n");                           //
        buffer.append("结束 SOC:").append(endSoc).append("\n");                             //
        buffer.append("充电结束原因:").append(endReason).append("\n");                          //
        buffer.append("本次充电电量:").append(chargingQuantity).append("\n");                //
        buffer.append("充电前电表读数:").append(beforeChargingValue).append("\n");             //
        buffer.append("充电后电表读数:").append(afterChargingValue).append("\n");              //
        buffer.append("本次充电金额:").append(chargingAmount).append("\n");                  //
        buffer.append("内部索引号:").append(indexNum).append("\n");                           //
        buffer.append("充电前卡余额:").append(beforeChargingBalance).append("\n");           //
        buffer.append("当前充电记录索引:").append(curIndex).append("\n");                           //
        buffer.append("总充电记录条目:").append(totalRecordCount).append("\n");                   //
        buffer.append("预留v3:").append(v3).append("\n");                                 //
        buffer.append("充电策略:").append(chargingStrategy).append("\n");                   //
        buffer.append("充电策略参数:").append(chargingStrategyParam).append("\n");           //
        buffer.append("车辆 VIN:").append(vin).append("\n");                             //
        buffer.append("车牌号:").append(carNum).append("\n");                      //
        buffer.append("时段1充电电量:").append(t1ChargingQuantity).append("\n");              //
        buffer.append("时段2充电电量:").append(t2ChargingQuantity).append("\n");              //
        buffer.append("启动方式:").append(startWay).append("\n");                           //
        buffer.append("充电流水号:").append(serialNum).append("\n");                       //
        buffer.append("充电服务费:").append(serviceCost).append("\n");                     //
        buffer.append("千分位电量:").append(thousandthEnergy).append("\n");                //
        return buffer.toString();
    }
}
